/**APUE
 * 16.2 写一个程序, 在至少两种不同的平台上打印出所支持套接字的stat结构成员,并且描述这些结果的不同之处 
 */


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>


#define LISTEN_PORT       8000
#define BUF_SIZE_MAX      1024

static void print_err(char *str, int line, int err_no) {
    if (str) {
        printf("line %d %s: %s\n", line, str, strerror(err_no));
    }
    
    exit(-1);
}

#if 0
struct stat {
    dev_t     st_dev;         /* ID of device containing file */
    ino_t     st_ino;         /* Inode number */
    mode_t    st_mode;        /* File type and mode */
    nlink_t   st_nlink;       /* Number of hard links */
    uid_t     st_uid;         /* User ID of owner */
    gid_t     st_gid;         /* Group ID of owner */
    dev_t     st_rdev;        /* Device ID (if special file) */
    off_t     st_size;        /* Total size, in bytes */
    blksize_t st_blksize;     /* Block size for filesystem I/O */
    blkcnt_t  st_blocks;      /* Number of 512B blocks allocated */

    /* Since Linux 2.6, the kernel supports nanosecond
       precision for the following timestamp fields.
       For the details before Linux 2.6, see NOTES. */

    struct timespec st_atim;  /* Time of last access */
    struct timespec st_mtim;  /* Time of last modification */
    struct timespec st_ctim;  /* Time of last status change */

#define st_atime st_atim.tv_sec      /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
#endif

void print_stat(struct stat *s) {
    if (s == NULL) return;

    printf("ID of device containing file: %d\n", s->st_dev);
    printf("Inode number: %d\n", s->st_ino);
	printf("File type and mode: %d\n", s->st_mode);
	printf("Number of hard links: %d\n", s->st_nlink);
    printf("User ID of owner: %d\n", s->st_uid);
    printf("Group ID of owner: %d\n", s->st_gid);
	printf("Device ID (if special file) : %d\n", s->st_rdev );
	printf("Total size, in bytes: %d\n", s->st_size );
	printf("Block size for filesystem I/O: %d\n", s->st_blksize );
	printf("Number of 512B blocks allocated: %d\n", s->st_blocks );
}

int main() {
    struct sockaddr_in sockaddr;
    int sockfd;
    
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) print_err("sock fail", __LINE__, errno); 

    struct stat stat_buf;
    int ret = fstat(sockfd, &stat_buf);
    if (ret == -1) print_err("fstat fail", __LINE__, errno);
    
    printf("IPv4 socket stat = {\n");
    print_stat(&stat_buf);
    printf("}\n");

    close(sockfd);

    sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
    ret = fstat(sockfd, &stat_buf);
    if (ret == -1) print_err("fstat fail", __LINE__, errno);

    printf("IPv4 socket stat = {\n");
    print_stat(&stat_buf);
    printf("}\n");

    close(sockfd);

    return 0;
}
